﻿using System;
using MemoDb.Tests.Model.Ids;
using NUnit.Framework;

namespace MemoDb.Tests
{
    [TestFixture]
    public class IdsTests
    {
        [Test]
        public void AutoAssignInt()
        {
            TestAutoAssign<int>((a, b) => b == a + 1);
        }

        [Test]
        public void AssignIdOnInsert()
        {
            var memo = new Memo( assignIdMode: AssignIdMode.OnInsert)
                .Map<Item<int>>(c => c.SetId<int>("Id", x=>10));

            var item = new Item<int>
            {
                Name = "item a"
            };


            using (var s = memo.CreateSession())
            {
                s.Insert(item);
                Assert.AreEqual(10, item.Id);
            }
        }

        [Test]
        public void AssignIdOnFlush()
        {
            var memo = new Memo(assignIdMode: AssignIdMode.OnFlush)
                .Map<Item<int>>(c => c.SetId<int>("Id", x => 10));

            var item = new Item<int>
                           {
                               Name = "item a"
                           };


            using (var s = memo.CreateSession())
            {
                s.Insert(item);
                Assert.AreEqual(default(int), item.Id);
                s.Flush();
                Assert.AreEqual(10, item.Id);
            }
        }

        [Test]
        public void AutoAssignLong()
        {
            TestAutoAssign<long>((a, b) => b == a + 1);
        }

        [Test]
        public void AutoAssignGuid()
        {
            TestAutoAssign<Guid>();
        }

        [Test]
        public void AutoAssignCustom()
        {
            var memo = new Memo()
                .Map<Item<int>>(c => c.SetId(x => x.Id, x => x + 10));

            Test<int>(memo, (a, b) => b == a + 10);
        }

        [Test]
        public void Assigned()
        {
            var memo = new Memo()
                .Map<Item<int>>(c => c.SetId("Id"));

            var a = new Item<int>
            {
                Name = "item a",
                Id = 222
            };

            var b = new Item<int>
            {
                Name = "item b",
                Id = 111
            };

            Test(memo, a, b, (ida,idb) => ida == 222 && idb == 111);
        }

        private static void TestAutoAssign<TId>(Func<TId,TId,bool> testIds = null)
        {
            var memo = new Memo()
                .Map<Item<TId>>(x=>x.SetId("Id", autoAssign: true));

            Test(memo, testIds);
        }

        private static void Test<TId>(Memo memo, Func<TId, TId, bool> testIds)
        {
            var a = new Item<TId>
                        {
                            Name = "item a"
                        };

            var b = new Item<TId>
                        {
                            Name = "item b"
                        };

            Test(memo, a, b, testIds);
        }

        private static void Test<TId>(Memo memo, Item<TId> a, Item<TId> b, Func<TId, TId, bool> testIds)
        {
            using (var s = memo.CreateSession())
            {
                s.Insert(a);
                s.Insert(b);
                s.Flush();
            }
         
            Assert.AreNotEqual(a.Id, b.Id);
            if (testIds != null) 
                testIds(a.Id, b.Id);
        }
    }
}